#include "common.h"

#include "NetworkClient.h"
#include "Device.hpp"
#include "DevicePropeller.h"
#include "DeviceBattery.h"
#include "DeviceInertialNavigation.h"
#include "DeviceDepth.h"
#include "DeviceHeight.h"
#include "DeviceSwitch.h"
#include "ThreadUtils.hpp"
#include "PID_Control.h"
#include "Order.h"
#include "Gpio.h"

using namespace std;

atomic<bool> running(true); // 用于控制线程的运行状态

void handle_client(int argc,char *argv[],NetworkClient& client);
void handle_client_net(int acc_fd);
void threadFunc(int interval);
void auto_send_thread(int interval);
void recordData(int interval);

NetworkClient client("192.168.1.123", PORT);

// 全局标志：是否需要退出程序
volatile bool shouldExit = false;

void handleSigInt(int signum) {
    cout << "\n收到 Ctrl+C 信号，准备退出..." <<signum<< endl;
    shouldExit = true;

    exit(0) ;
}

int main(int argc, char *argv[]){
    if (signal(SIGINT, handleSigInt) == SIG_ERR) {
        printf("无法注册信号处理函数\n");
        return 1;
    }

    ifstream file("data.json");

    if (!file.is_open()) {
        cerr << "Failed to open file" << endl;
        return 1;
    }

    // 解析 JSON 文件
    try{
        file >> j;
    } catch(const exception& e){
        cerr << "Json error: " << e.what() << endl;
    }

    client.setIp(j["IP"]);

    if (!client.connect()) {
        cerr << "Failed to connect to server" << endl;
        return -1;
    }

    cout << "Connected to server at "<<j["IP"]<<":" << PORT << endl;
    
    // 开启实时更新传感器数据的线程
    thread updateThread(threadFunc, 300);
    updateThread.detach();

    cout<<"已经开启实时更新传感器数据的线程"<<endl;
    
    // 输入额外参数,进入手动模式
    if(argc > 1){
        handle_client(argc,argv,client);

        return 0;
    }

    try {
        client.func("请输入数字:\n1 深度计高度计\n2 电池\n3 推进器\n4 惯导");
    } catch (const exception& e) {
        cerr << "Network error: " << e.what() << endl;
    }

    // 实时向上发送传感器消息
    thread autoSendThread(auto_send_thread, 1);
    autoSendThread.detach();

    // 将数据保存到硬盘
    thread recordDataThread(recordData, 300);
    recordDataThread.detach();

    handle_client_net(client.m_socketFd);

    return 0;
}

void handle_client(int argc,char *argv[],NetworkClient& client){
    // 尾推
    DevicePropeller devicePropeller(j["Propeller"],"can");
    Device<Propeller> &device_propeller = devicePropeller;

    // ttyCH9344USB5 继电器
    // DeviceSwitch deviceSwitch(j["Switch"],"SerialPort");
    DeviceSwitch deviceSwitch(j["Switch"],"SerialPort");
    Device<int> &device_switch = deviceSwitch;
    
    thread t1;
    
    int a = 0;
    
    if(argc >= 2){
        switch (atoi(argv[1]))
        {
        case 1:
            // client.m_socketFd = inet_addr(argv[2]);
            // server_addr.sin_addr.s_addr = inet_addr(argv[2]); // 服务器IP地址

            break;
        // 手动调整尾推角度
        case 2:{

            // cout<<atoi(argv[4])<<endl;
            if (argc > 6)
            {
                while(!shouldExit){
                    usleep(atoi(argv[6])*1000);
                    propeller.mode = atoi(argv[2]);
                    propeller.angle = atoi(argv[3]);

                    t1 = ThreadUtils::createThread(&devicePropeller, &DevicePropeller::func, propeller);
                    t1.detach();

                    propeller.mode = atoi(argv[4]);
                    propeller.angle = atoi(argv[5]);

                    t1 = ThreadUtils::createThread(&devicePropeller, &DevicePropeller::func, propeller);
                    t1.detach();
                }

                break;
            }
            
            propeller.mode = atoi(argv[2]);
            propeller.angle = atoi(argv[3]);

            t1 = ThreadUtils::createThread(&devicePropeller, &DevicePropeller::func, propeller);
            t1.detach();

            break;
        }
        // 获取电池数据
        case 3:
            printf("v\t\tI\t\tsoc\n");
            
            for(;!shouldExit;){
                sleep(1);
                // device_battery.func(battery_data);
                
                printf("%f\t%f\t%f\n",
                    battery_data.v,battery_data.I ,battery_data.soc);
            }
            
            break;
        // 获取惯导数据
        case 4:{
            // float angular_velocity_x; // 载体角速度X轴
            // float angular_velocity_y; // 载体角速度Y轴
            // float angular_velocity_z; // 载体角速度Z轴
            // float acceleration_x; // 载体加速度X轴
            // float acceleration_y; // 载体加速度Y轴
            // float acceleration_z; // 载体加速度Z轴
            // float latitude; // 纬度
            // float longitude; // 经度
            // float altitude; // 高度
            // float velocity_east; // 东向速度
            // float velocity_north; // 北向速度
            // float velocity_up; // 天向速度

            if(atoi(argv[2]) == 1){
                printf("utc_time\theading\t\troll\t\tpitch\t\t\tacceleration_x\n");
    
                for(;!shouldExit;){
                    // device_inertialNavigation.func(aipov_data);
                    if(argc>2){
                        usleep(atof(argv[2])*1000000);
                    }else{
                        sleep(1);
                    }
                    
                    printf("%f\t%f\t%f\t%f\t%f\t%lx\n",
                        aipov_data.utc_time,aipov_data.heading ,aipov_data.roll,aipov_data.pitch,aipov_data.acceleration_x,aipov_data.hex1);
                }
            }else if(atoi(argv[2]) == 2){
                DeviceInertialNavigation deviceInertialNavigation(j["InertialNavigation"],"SerialPort");
                deviceInertialNavigation.sendMessage("$HOSTCTL,8,10,5*00");
            }else if(atoi(argv[2]) == 3){
                DeviceInertialNavigation deviceInertialNavigation(j["InertialNavigation"],"SerialPort");
                deviceInertialNavigation.sendMessage("$HOSTCTL,8,10,4*00");
            }

            break;
        }
        // 获取高度数据
        case 5:{
            // Gpio gpio("18");
            // gpio.gpioOpen();

            cout<<"height"<<endl;
            for(;!shouldExit;){
                sleep(1);
                
                cout << height <<endl;
            }

            break;

        }
        // 获取深度计数据
        case 6:
            cout<<"depth\tpressure\ttemperature"<<endl;
            for(;!shouldExit;){
                sleep(1);
                
                cout<<depth_data.depth<<"\t"<<depth_data.pressure<<"\t\t"<<depth_data.temperature<<endl; 
            }

            break;
        // 向地面站发送报文
        case 7:
            try {
                // cout<<argv[2]<<endl;
                char buf[75] = {0};
                strncpy(buf, argv[2], 74);
                buf[74] = '\0'; // 确保字符串以空字符终止
                
                client.func(buf);
            } catch (const exception& e) {
                cerr << "case 7 error: " << e.what() << endl;
            }
            
            break;
        // 打开开关
        case 8:
            cout<<j["Switch"]<<endl;
            a = atoi(argv[2]);
            device_switch.func(a);

            break;
        // 航向控制
        case 9:
            ToHeading(atof(argv[2]), device_propeller);
            // ToPoint(atof(argv[2]), atof(argv[3]), device_propeller);
            // ToVelocity(atof(argv[2]), device_propeller);

            break;
        // 深度控制
        case 10:
            ToDepth(atof(argv[2]), device_propeller);
            break;
        // 执行使命文件
        case 11:{
            Order order(j["orderFile"]);

            order.func(devicePropeller);

            break;
        }
        // 可控电源控制
        case 12:{
            Gpio gpio0(argv[2]);

            if(atof(argv[3]) == 1){
                gpio0.gpioOpen();
            }else if(atof(argv[3])  == 0 ){
                gpio0.gpioClose();
            }else if(atof(argv[3])  == 2 ){
                gpio0.getStatus();
            }
            
            break;
        }

        default:
            break;
        }
    }
}

void threadFunc(int interval) {
    auto start = chrono::steady_clock::now();

    // ttyCH9344USB2 惯导
    DeviceInertialNavigation deviceInertialNavigation(j["InertialNavigation"],"SerialPort");
    // Device<Aipov_Data> &device_inertialNavigation = deviceInertialNavigation;

    // ttyCH9344USB0 深度计
    DeviceDepth deviceDepth(j["Depth"],"SerialPort");
    // Device<Depth_data> &device_Depth = deviceDepth;
    
    // can2 电池
    DeviceBattery deviceBattery(j["Battery"],"can");
    // Device<Battery_data> &device_battery = deviceBattery;

    // ttyCH9344USB1 高度计
    DeviceHeight deviceHeight(j["Height"],"SerialPort");
    // Device<float> &device_Height = deviceHeight;
    
    thread t1;

    while (running && !shouldExit) {
        this_thread::sleep_until(start + chrono::milliseconds(interval)); // 等待到指定时间点

        t1 = ThreadUtils::createThread(&deviceInertialNavigation, &DeviceInertialNavigation::func, ref(aipov_data));
        t1.detach();
        // deviceInertialNavigation.func(aipov_data);

        t1 = ThreadUtils::createThread(&deviceBattery, &DeviceBattery::func, ref(battery_data));
        t1.detach();
        // deviceBattery.func(battery_data);
        
        t1 = ThreadUtils::createThread(&deviceHeight, &DeviceHeight::func, ref(height));
        t1.detach();
        // deviceHeight.func(height);

        
        t1 = ThreadUtils::createThread(&deviceDepth, &DeviceDepth::func, ref(depth_data));
        t1.detach();
        // deviceDepth.func(depth_data);

        // cout<<"--"<<endl;
        start = chrono::steady_clock::now(); // 重置时间点
    }
    
    return;
}

// 处理客户端的网络请求
void handle_client_net(int acc_fd) {
    DevicePropeller devicePropeller(j["Propeller"],"can");
    // Device<Propeller> &device_propeller = devicePropeller;

    // 继电器
    DeviceSwitch deviceSwitch(j["Switch"],"SerialPort");
    // Device<int> &device_switch = deviceSwitch;
    
    thread t1;

    int a = 0;
    unsigned char buf[BUFFER_SIZE] = {0};
    int byte;

    int flag = 0;

    while (1 && (!shouldExit)) {
        // 接收TCP消息
        byte = recv(acc_fd, buf, sizeof(buf), 0);
        if (byte > 0) {
            // 根据消息的内容选择不同的执行
            switch ((unsigned)buf[2]) {
                // 深度计 高度计
                case 0x01:{
                    printf("case 1\n");

                    char result[1024], buf[BUFFER_SIZE] = {0}; // 目标缓冲区
                    memset(result,0,1024);
                    memset(buf,0,BUFFER_SIZE);

                    // 使用 snprintf 将数字格式化并拼接到字符串中
                    // 深度计数据,高度,pressure,temperature
                    snprintf(result, sizeof(result), "%f,%f,%f,%f", 
                    depth_data.depth,height,depth_data.pressure,depth_data.temperature);

                    client.func(result);
 
                    break;
                }
                // 电池
                case 0x02:{
                    printf("case 2\n");
                    
                    char result[1024], buf[BUFFER_SIZE] = {0}; // 目标缓冲区
                    memset(result,0,1024);
                    memset(buf,0,BUFFER_SIZE);

                    snprintf(result, sizeof(result), "%f,%f,%f", battery_data.v,battery_data.I,battery_data.soc);

                    client.func(result);

                    break;
                }
                // 推进器
                case 0x03:{
                    cout<<"case 3"<<endl;

                    int a = (int)buf[3];

                    uint16_t value = (static_cast<uint16_t>(buf[5]) << 8) | buf[4];
                    int b = static_cast<int16_t>(value);

                    cout<<"输入角度:"<<b<<endl;

                    if(a == 1){
                        a = 2;
                    }else if(a == 2){
                        a = 1;
                    }
                    
                    propeller.mode = a;
                    propeller.angle = b;
                
                    t1 = ThreadUtils::createThread(&devicePropeller, &DevicePropeller::func, propeller);
                    
                    t1.detach();

                    break;
                }
                // 惯导
                case 0x04:{
                    printf("case 4\n");
                    
                    
                    if((unsigned)buf[3] == 1){
                        char result[1024], buf[BUFFER_SIZE] = {0}; // 目标缓冲区
                        memset(result,0,1024);
                        memset(buf,0,BUFFER_SIZE);
    
                        // 使用 snprintf 将数字格式化并拼接到字符串中
                        // 惯导数据
                        snprintf(result, sizeof(result), 
                        "utc_time:%f, angular_velocity_x:%f, angular_velocity_y:%f, angular_velocity_z:%f\nacceleration_x:%f, acceleration_y:%f, acceleration_z:%f", 
                        aipov_data.utc_time, aipov_data.angular_velocity_x, aipov_data.angular_velocity_y, aipov_data.angular_velocity_z,
                        aipov_data.acceleration_x,aipov_data.acceleration_y,aipov_data.acceleration_z);
                        
                        client.func(result);
                        
                    }else if((unsigned)buf[3] == 2){
                        DeviceInertialNavigation deviceInertialNavigation(j["InertialNavigation"],"SerialPort");
                        deviceInertialNavigation.sendMessage("$HOSTCTL,8,10,5*00");
                    }else if((unsigned)buf[3] == 3){
                        DeviceInertialNavigation deviceInertialNavigation(j["InertialNavigation"],"SerialPort");
                        deviceInertialNavigation.sendMessage("$HOSTCTL,8,10,4*00");
                    }

                    break;
                }
                // 开关
                case 0x05:{
                    printf("case 5\n");
                    
                    a = (int)buf[3];

                    if(a < 8){
                        t1 = ThreadUtils::createThread(&deviceSwitch, &DeviceSwitch::func, a);
                        t1.detach();

                    }else {
                        // cout<<"string:"<<to_string(a)<<endl;
                        Gpio gpio(to_string(a).c_str());
                        if(buf[4] == 1){
                            gpio.gpioOpen();
                        }else if(buf[4] == 0){
                            gpio.gpioClose();
                        }
                    }
                    // device_switch.func(a);

                    break;
                }
                // 使命文件
                case 0x06:{
                    cout<<"case 6 使命文件操作"<<endl;
                    if(buf[3] == 0x01){
                        // 使命执行

                    }else if(buf[3] == 0x02){
                        // 使命终止

                    }
                    break;
                }
                // 终止
                case 0x00:{
                    printf("Exiting the loop\n");
                    goto exit_loop;
                }
                // 心跳包
                case 0xD2:{
                    if(flag == 0){
                        printf("接收到心跳包\n");
                        flag = 1;
                    }
                    break;
                }
                // 天线接收信息后的反馈
                case 0x44:{
                    
                    break;
                }
                // 其他情况
                default:
                    printf("error\n");
                    break;
            }
        } else if (byte == 0) {
            printf("Client closed connection\n");
            break;
        } else {
            perror("recv error");
            break;
        }

        memset(buf, 0, sizeof(buf));
    }

    exit_loop:

    send(acc_fd, "开发板关闭\n", strlen("开发板关闭\n"), 0);
}

void auto_send_thread(int interval){
    // vector<pair<float, float>> coordinates = {
    //     {116.352001f, 40.260119f},
    //     {116.349103f, 40.239018f},
    //     {116.369310f, 40.239090f},
    //     {116.369899f, 40.255820f},
    //     {116.395261f, 40.255567f},
    //     {116.390073f, 40.236630f},
    //     {116.409591f, 40.239824f},
    //     {116.409601f, 40.255243f},
    //     {116.424482f, 40.256387f},
    //     {116.420470f, 40.214457f},
    //     {116.332431f, 40.219330f},
    //     {116.337036f, 40.262049f},
    //     {116.353742f, 40.274183f},
    //     {116.453770f, 40.273954f},
    //     {116.443384f, 40.224985f}
    // };
    // auto it = coordinates.begin();

    // aipov_data.acceleration_z = 9.8;
    
    auto start = chrono::steady_clock::now(); // 获取当前时间点
    char buffer[BUFFER_SIZE] = {0};
    int offset = 0;

    while (running && (shouldExit != true)) {
        this_thread::sleep_until(start + chrono::seconds(interval)); // 等待到指定时间点
        
        // 清零缓冲区
        memset(buffer, 0, BUFFER_SIZE);
        offset = 0;
        
        // 序列化depthGauge数据
        serialize_item(buffer, &depth_data.depth, sizeof(float), &offset);
        serialize_item(buffer, &height, sizeof(float), &offset);
        serialize_item(buffer, &depth_data.pressure, sizeof(float), &offset); //
        serialize_item(buffer, &depth_data.temperature, sizeof(float), &offset); 

        // 序列化battery数据
        serialize_item(buffer, &battery_data.I, sizeof(float), &offset);
        serialize_item(buffer, &battery_data.soc, sizeof(float), &offset);
        serialize_item(buffer, &battery_data.v, sizeof(float), &offset);

        // 序列化dvl数据
        serialize_item(buffer, &aipov_data.utc_time, sizeof(float), &offset);
        serialize_item(buffer, &aipov_data.heading, sizeof(float), &offset);//偏航角
        serialize_item(buffer, &aipov_data.pitch, sizeof(float), &offset);//俯仰角
        serialize_item(buffer, &aipov_data.roll, sizeof(float), &offset);//横滚角
        serialize_item(buffer, &aipov_data.acceleration_x, sizeof(float), &offset);//
        serialize_item(buffer, &aipov_data.acceleration_y, sizeof(float), &offset);//
        serialize_item(buffer, &aipov_data.acceleration_z, sizeof(float), &offset);//

        // if(it==coordinates.end()){
        //     it = coordinates.begin();
        // }
        serialize_item(buffer, &aipov_data.latitude, sizeof(float), &offset);
        serialize_item(buffer, &aipov_data.longitude, sizeof(float), &offset);
        // it++;

        unsigned char second_last_digit = (aipov_data.hex1 >> 4) & 0xF;
    
        // 判断该位是否为0x2
        if (second_last_digit == 0x1) {
            cout << "倒数第二位是1，执行相应操作..." << endl;
            buffer[68] = 0x01;
            // 此处添加需要执行的逻辑
        } else if (second_last_digit == 0x8)  {
            cout << "倒数第二位是8，执行相应操作..." << endl;
            buffer[68] = 0x02;
        }else {
            // cout << "倒数第二位不是8或2" << endl;
            buffer[68] = 0x00;
        }
        
        buffer[69] = 0x66;

        try {
            client.func(buffer);      
        } catch (const exception& e) {
            cerr << "auto_send_thread error: " << e.what() << endl;
        }

        start = chrono::steady_clock::now(); // 重置时间点
    }

    cout << "Timer thread is stopping." << endl; // 线程停止时输出消息
}

// 定时记录数据
void recordData(int interval) {
    vector<vector<string>> data = {
        {"Name", "Age", "City"},
        {"Alice", "25", "New York"},
        {"Bob", "30", "Los Angeles"},
        {"Charlie", "35", "Chicago"}
    };

    string currentTime = getCurrentTime();

    // 拼接字符串
    string filename = "./csv/output" + currentTime + ".csv";

    writeCSV(filename, data);

    vector<vector<string>> data1 = {
        {"nihao", "25", "New York"},
        {"hao", "30", "Los Angeles"},
        {"ni", "35", "Chicago"}
    };

    writeCSV(filename, data1);

    cout << "数据已写入文件: " << filename <<interval<< endl;

    return;
}